package com.enjoy.concurrent.ch8;

import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.atomic.AtomicInteger;

public class JobInfo<R> {

    //工作名称，用以区分框架中唯一的工作
    private final String jobName;

    //工作任务的长度
    private final int jobLength;
    //处理任务的接口
    private ITaskProcessor<R, ?> taskProcessor;

    //任务成功处理的数量
    private AtomicInteger successCount;
    //任务已经处理的数量
    private AtomicInteger taskProcessCount;

    //存放每个任务的处理结果，供查询用
    private LinkedBlockingDeque<TaskResult<R>> taskProcessQueue;

    private static CheckJobProcessor checkJobProcessor = CheckJobProcessor.getInstance();

    //保留任务结果的时长
    private final long expireTime;

    public JobInfo(String jobName, int length, ITaskProcessor<R, ?> taskProcessor, long expireTime) {
        this.jobName = jobName;
        this.jobLength = length;
        this.taskProcessor = taskProcessor;
        this.successCount = new AtomicInteger(0);
        this.taskProcessCount = new AtomicInteger(0);
        this.taskProcessQueue = new LinkedBlockingDeque<>(length);
        this.expireTime = expireTime;
    }

    public ITaskProcessor<R, ?> getTaskProcessor() {
        return taskProcessor;
    }

    public void setTaskProcessor(ITaskProcessor<R, ?> taskProcessor) {
        this.taskProcessor = taskProcessor;
    }

    public LinkedBlockingDeque<TaskResult<R>> getTaskProcessQueue() {
        return taskProcessQueue;
    }

    public void setTaskProcessQueue(LinkedBlockingDeque<TaskResult<R>> taskProcessQueue) {
        this.taskProcessQueue = taskProcessQueue;
    }

    //提供工作的整体进度信息
    public String getTotalProcess() {
        return "success:" + successCount.get() + " current:" + taskProcessCount.get() + " total:" + jobLength;
    }

    //提供工作中每个任务的处理结果
    public List<TaskResult<R>> getTaskDetail() {
        List<TaskResult<R>> taskResultList = new LinkedList<>();
        TaskResult<R> taskResult;
        while ((taskResult = taskProcessQueue.pollFirst()) != null) {
            taskResultList.add(taskResult);
        }
        return taskResultList;
    }


    /**
     * 每个任务处理完成后，记录任务的处理结果，
     * 因为从业务应用的角度来说，对查询任务进度
     * 数据的一致性要求不高，我们保证最终一致性即可，
     * 无需对这个方法加锁
     */
    public void addTaskResult(TaskResult<R> taskResult) {
        if (TaskResultType.SUCCESS.equals(taskResult.getResult())) {
            successCount.incrementAndGet();
        }
        taskProcessCount.incrementAndGet();
        taskProcessQueue.addLast(taskResult);
        if (taskProcessCount.get() == jobLength) {
            //工作的结果放到定时缓存，到期后清除
            checkJobProcessor.putJob(jobName, expireTime);
        }
    }

}
